package com.huayun.plugin.fastener.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.huayun.plugin.fastener.vo.FiberMaterial;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.*;

@Service
public class FileParser {

    /**
     * 解析XML文件并将其转换为JSON格式。
     *
     * @param file 待解析的XML文件
     * @return JSON格式的字符串，表示解析后的数据
     * @throws Exception 如果解析过程中发生错误
     */
    public String parseXml(MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(inputStream);
        Element root = document.getDocumentElement();

        Map<String, Object> result = new HashMap<>();
        parseElement(root, result);

        // 将Map转换为JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResult = objectMapper.writeValueAsString(result);
        System.out.println(jsonResult);
        return jsonResult;
    }

    /**
     * 递归解析XML元素并将其存储到Map中。
     *
     * @param element 当前XML元素
     * @param result  存储解析结果的Map
     */
    private void parseElement(Element element, Map<String, Object> result) {
        String nodeName = element.getNodeName();
        Map<String, Object> nodeMap = new HashMap<>();

        // 添加属性
        if (element.hasAttributes()) {
            for (int i = 0; i < element.getAttributes().getLength(); i++) {
                Node attr = element.getAttributes().item(i);
                nodeMap.put(attr.getNodeName(), attr.getNodeValue());
            }
        }

        // 添加子节点
        NodeList children = element.getChildNodes();
        List<Map<String, Object>> childList = new ArrayList<>();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                Map<String, Object> childMap = new HashMap<>();
                parseElement((Element) child, childMap);
                childList.add(childMap);
            }
        }

        if (!childList.isEmpty()) {
            nodeMap.put("children", childList);
        }

        result.put(nodeName, nodeMap);
    }

    /**
     * 解析BDF文件并提取特定类型的数据行。
     *
     * @param file 待解析的BDF文件
     * @return 包含不同数据类型的Map集合
     */
    public Map<String, List<Map<String, Object>>> parseBDFFile(MultipartFile file) {
        List<Map<String, Object>> gridLines = new ArrayList<>();
        List<Map<String, Object>> cbarLines = new ArrayList<>();
        List<Map<String, Object>> ctria3Lines = new ArrayList<>();
        List<Map<String, Object>> cquad4Lines = new ArrayList<>();
        List<Map<String, Object>> pcompLines = new ArrayList<>();
        List<Map<String, Object>> matLines = new ArrayList<>(); // 添加
        try (BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (line.startsWith("GRID")) {
                    gridLines.add(processLineGrid(line));
                } else if (line.startsWith("CBAR")) {
                    cbarLines.add(processLineCBAR(line));
                } else if (line.startsWith("CTRIA3")) {
                    ctria3Lines.add(processLineCTRIA3(line));
                } else if (line.startsWith("CQUAD4")) {
                    cquad4Lines.add(processLineCQUAD4(line));
                } else if (line.startsWith("MAT8")) {
                    String line1 = br.readLine();
                    System.out.println(line1);
                    matLines.add(processLineMat(line, line1));
                } else if (line.startsWith("PCOMP")) {
                    pcompLines.add(processLinePComp(line)); // 添加PCOMP行
                    while ((line = br.readLine()) != null && !line.trim().isEmpty()) {
                        System.out.println(line);
                        if (line == null || line.isEmpty()) {
                            continue;
                        }
                        pcompLines.add(processLinePComp(line)); // 继续添加直到ENDDATA
                        if(line.length()> 40) {
                            pcompLines.add(processLinePComp1(line)); // 继续添加直到ENDDATA
                        }

                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        Map<String, List<Map<String, Object>>> result = new HashMap<>();
        result.put("GRID", gridLines);
        result.put("CBAR", cbarLines);
        result.put("CTRIA3", ctria3Lines);
        result.put("CQUAD4", cquad4Lines);
        result.put("pcomp", pcompLines);
        result.put("mat", matLines);
        return result;
    }

    /**
     * 处理GRID行数据并提取节点信息。
     *
     * @param line GRID行数据
     * @return 包含节点信息的Map
     */
    private Map<String, Object> processLineGrid(String line) {
        // 这里可以添加具体的处理逻辑
        int nodeId = Integer.parseInt(line.substring(8, 16).trim());
        double x, y, z;
        Integer strLen = line.length();
        if (hasContentAroundHyphen(line.substring(24, 32).trim())) {
            x = 0.0;
        } else {
            x = Double.parseDouble(line.substring(24, 32).trim());
        }

        if (hasContentAroundHyphen(line.substring(32, 40).trim())) {
            y = 0.0;
        } else {
            y = Double.parseDouble(line.substring(32, 40).trim());
        }
        if (hasContentAroundHyphen(line.substring(40, line.length()).trim())) {
            z= 0.0;
        } else {
            z = Double.parseDouble(line.substring(40, line.length()).trim());
        }
//        System.out.println("Node ID: " + nodeId + ", Coordinates: (" + x + ", " + y + ", " + z + ")");
        Map<String, Object> gridMap = new HashMap<>();
        gridMap.put("nodeId", nodeId);
        gridMap.put("x", x);
        gridMap.put("y", y);
        gridMap.put("z", z);
        return gridMap;
    }

    /**
     * 处理CBAR行数据并提取元素信息。
     *
     * @param line CBAR行数据
     * @return 包含元素信息的Map
     */
    private Map<String, Object> processLineCBAR(String line) {
        // 这里可以添加具体的处理逻辑
        int elementId = Integer.parseInt(line.substring(8, 16).trim());
        int pcompId = Integer.parseInt(line.substring(16, 24).trim());
        int n1 = Integer.parseInt(line.substring(24, 32).trim());
        int n2 = Integer.parseInt(line.substring(32, 40).trim());

//        System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 + ", " + n3 + ", " + n4);
        Map<String, Object> CBARMap = new HashMap<>();
        CBARMap.put("nodeId", elementId);
        CBARMap.put("pcompId", pcompId);
        CBARMap.put("n1", n1);
        CBARMap.put("n2", n2);
        return CBARMap;
    }

    /**
     * 处理CTRIA3行数据并提取元素信息。
     *
     * @param line CTRIA3行数据
     * @return 包含元素信息的Map
     */
    private Map<String, Object> processLineCTRIA3(String line) {
        // 这里可以添加具体的处理逻辑
        int elementId = Integer.parseInt(line.substring(8, 16).trim());
        int pcompId = Integer.parseInt(line.substring(16, 24).trim());
        int n1 = Integer.parseInt(line.substring(24, 32).trim());
        int n2 = Integer.parseInt(line.substring(32, 40).trim());
        int n3 = Integer.parseInt(line.substring(40, 48).trim());
//        System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 + ", " + n3 + ", " + n4);
        Map<String, Object> CTRIA3Map = new HashMap<>();
        CTRIA3Map.put("nodeId", elementId);
        CTRIA3Map.put("pcompId", pcompId);
        CTRIA3Map.put("n1", n1);
        CTRIA3Map.put("n2", n2);
        CTRIA3Map.put("n3", n3);
        return CTRIA3Map;
    }

    /**
     * 处理CQUAD4行数据并提取元素信息。
     *
     * @param line CQUAD4行数据
     * @return 包含元素信息的Map
     */
    private Map<String, Object> processLineCQUAD4(String line) {
        // 这里可以添加具体的处理逻辑
        int elementId = Integer.parseInt(line.substring(8, 16).trim());
        int pcompId = Integer.parseInt(line.substring(16, 24).trim());
        int n1 = Integer.parseInt(line.substring(24, 32).trim());
        int n2 = Integer.parseInt(line.substring(32, 40).trim());
        int n3 = Integer.parseInt(line.substring(40, 48).trim());
        int n4 = Integer.parseInt(line.substring(48, 56).trim());
//        System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 + ", " + n3 + ", " + n4);
        Map<String, Object> CQUAD4Map = new HashMap<>();
        CQUAD4Map.put("nodeId", elementId);
        CQUAD4Map.put("pcompId", pcompId);
        CQUAD4Map.put("n1", n1);
        CQUAD4Map.put("n2", n2);
        CQUAD4Map.put("n3", n3);
        CQUAD4Map.put("n4", n4);
        return CQUAD4Map;
    }

    /**
     * 处理PCOMP行数据并提取复合材料信息。
     *
     * @param line PCOMP行数据
     * @return 包含复合材料信息的Map
     */
    private Map<String, Object> processLinePComp(String line) {
        // 这里可以添加具体的处理逻辑
        Map<String, Object> PComp = new HashMap<>();

        if (line.substring(0, 8).trim().equals("PCOMP")) {
            String pcomp = line.substring(0, 8).trim();
            String elementId = line.substring(8, 16).trim();
            String n1 = line.substring(16, 24).trim();
            String n2 = line.substring(64, 72).trim();
            System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 );
            PComp.put("pcomp", pcomp);
            PComp.put("n0", elementId);
            PComp.put("n1", n1);
            PComp.put("n2", n2);

        } else {
            String elementId = line.substring(8, 16).trim();
            if (!(StringUtils.isNumeric(elementId))) {
                return new HashMap<>();
            }
            String n1 = line.substring(16, 24).trim();
            String n2 = line.substring(24, 32).trim();
            String n3 = line.substring(32, 40).trim();

            System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 + ", " + n3);

            PComp.put("n0", elementId);
            PComp.put("n1", n1);
            PComp.put("n2", n2);
            PComp.put("n3", n3);
        }


        return PComp;
    }

    private Map<String, Object> processLinePComp1(String line) {
        // 这里可以添加具体的处理逻辑
        Map<String, Object> PComp = new HashMap<>();
        String elementId = line.substring(40, 48).trim();
        if (!(StringUtils.isNumeric(elementId))) {
            return new HashMap<>();
        }
        String n1 = line.substring(48, 56).trim();
        String n2 = line.substring(56, 64).trim();
        String n3 = line.substring(64, 72).trim();
//        String n3 = line.substring(72, 80).trim();

        System.out.println("Element ID: " + elementId + ", Node IDs: " + n1 + ", " + n2 );

        PComp.put("n0", elementId);
        PComp.put("n1", n1);
        PComp.put("n2", n2);
        PComp.put("n3", n3);
        return PComp;
    }

    /**
     * 处理MAT8行数据并提取材料信息。
     *
     * @param line  MAT8行数据
     * @param line1 下一行数据
     * @return 包含材料信息的Map
     */
    private Map<String, Object> processLineMat(String line, String line1) {
        // 这里可以添加具体的处理逻辑
        String elementId = line.substring(8, 16).trim();
        String e1 = line.substring(16, 24).trim();
        String e2 = line.substring(24, 32).trim();
        String poissonRatio = line.substring(32, 40).trim();
        String g12 = line.substring(40, 48).trim();
//        String n5 = line1.substring(8, 16).trim();
//        String n6 = line1.substring(16, 24).trim();

        Map<String, Object> mat = new HashMap<>();
        mat.put("elementId", elementId);
        mat.put("e1", e1);
        mat.put("e2", e2);
        mat.put("poissonRatio", poissonRatio);
        mat.put("g12", g12);
//        mat.put("primaryThermalExpansion", n5);
//        mat.put("secondaryThermalExpansion", n6);
        return mat;
    }

    /**
     * 检查字符串是否包含有效的非连字符内容。
     *
     * @param str 待检查的字符串
     * @return 如果字符串包含有效的非连字符内容，则返回true；否则返回false
     */
    public static boolean hasContentAroundHyphen(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        // 匹配至少一个非 '-' 字符在 '-' 左右
        return str.matches(".*[^-]-[^-].*");
    }

    /**
     * 将CQUAD4数据导出为Excel文件。
     *
     * @param parsedData   解析后的数据
     * @param outputStream 输出流
     * @throws IOException 如果导出过程中发生IO错误
     */
    public void exportBdfToExcel(Map<String, List<Map<String, Object>>> parsedData, OutputStream outputStream) throws IOException {
        List<Map<String, Object>> cquad4Lines = parsedData.get("CQUAD4");
//        List<Map<String, Object>> gridLines = parsedData.get("GRID");
        List<Map<String, Object>> cbarLines = parsedData.get("CBAR");
        List<Map<String, Object>> ctria3Lines = parsedData.get("CTRIA3");
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("sheet1");

        // 创建表头
//        Row headerRow = sheet.createRow(0);
//        headerRow.createCell(0).setCellValue("CQUAD4");
//        headerRow.createCell(1).setCellValue("nodeId");
//        headerRow.createCell(2).setCellValue("n1");
//        headerRow.createCell(3).setCellValue("n2");
//        headerRow.createCell(4).setCellValue("n3");
//        headerRow.createCell(5).setCellValue("n4");

        // 填充数据
        int rowNum = 0;
        for (Map<String, Object> cbar : cbarLines) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue("CBAR");
            row.createCell(1).setCellValue((Integer) cbar.get("nodeId"));
            row.createCell(2).setCellValue((Integer) cbar.get("n1"));
            row.createCell(3).setCellValue((Integer) cbar.get("n2"));
        }
        for (Map<String, Object> ctria3 : ctria3Lines) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue("CTRIA3");
            row.createCell(1).setCellValue((Integer) ctria3.get("nodeId"));
            row.createCell(2).setCellValue((Integer) ctria3.get("n1"));
            row.createCell(3).setCellValue((Integer) ctria3.get("n2"));
            row.createCell(4).setCellValue((Integer) ctria3.get("n3"));
        }
        for (Map<String, Object> cquad4 : cquad4Lines) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue("CQUAD4");
            row.createCell(1).setCellValue((Integer) cquad4.get("nodeId"));
            row.createCell(2).setCellValue((Integer) cquad4.get("n1"));
            row.createCell(3).setCellValue((Integer) cquad4.get("n2"));
            row.createCell(4).setCellValue((Integer) cquad4.get("n3"));
            row.createCell(5).setCellValue((Integer) cquad4.get("n4"));
        }

        // 自动调整列宽
        for (int i = 0; i < 6; i++) {
            sheet.autoSizeColumn(i);
        }

        // 写入 OutputStream
        workbook.write(outputStream);
        workbook.close();
    }

    /**
     * 解析BDF格式的Excel文件并提取CQUAD4数据。
     *
     * @param inputStream 输入流
     * @return 包含CQUAD4数据的列表
     * @throws IOException 如果解析过程中发生IO错误
     */
    public List<Map<String, Object>> parseBdfExcelFile(InputStream inputStream) throws IOException {
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0); // 假设数据位于第一个工作表

        Iterator<Row> rowIterator = sheet.iterator();
        List<Map<String, Object>> bdfLines = new ArrayList<>();

        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();

            // 假设每列的顺序与提供的表格一致
            String nodeName = row.getCell(0).getStringCellValue();
            double nodeId = row.getCell(1).getNumericCellValue();
            double n1 = row.getCell(2).getNumericCellValue();
            double n2 = row.getCell(3).getNumericCellValue();

            if (nodeName.equals("CQUAD4")) {
                double n3 = row.getCell(4).getNumericCellValue();
                double n4 = row.getCell(5).getNumericCellValue();
                Map<String, Object> bdfMap = new HashMap<>();
                bdfMap.put("nodeName", nodeName);
                bdfMap.put("nodeId", nodeId);
                bdfMap.put("n1", n1);
                bdfMap.put("n2", n2);
                bdfMap.put("n3", n3);
                bdfMap.put("n4", n4);
                bdfLines.add(bdfMap);
            } else if(nodeName.equals("CBAR")) {
                Map<String, Object> bdfMap = new HashMap<>();
                bdfMap.put("nodeName", nodeName);
                bdfMap.put("nodeId", nodeId);
                bdfMap.put("n1", n1);
                bdfMap.put("n2", n2);
                bdfLines.add(bdfMap);
            } else if(nodeName.equals("CTRIA3")) {
                double n3 = row.getCell(4).getNumericCellValue();
                Map<String, Object> bdfMap = new HashMap<>();
                bdfMap.put("nodeName", nodeName);
                bdfMap.put("nodeId", nodeId);
                bdfMap.put("n1", n1);
                bdfMap.put("n2", n2);
                bdfMap.put("n3", n3);
                bdfLines.add(bdfMap);
            }


        }

        workbook.close();
        return bdfLines;
    }

    /**
     * 解析Excel文件并提取材料数据。
     *
     * @param inputStream 输入流
     * @return 包含材料数据的列表
     * @throws IOException 如果解析过程中发生IO错误
     */
    public List<FiberMaterial> parseExcelFile(InputStream inputStream) throws IOException {
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(1); // 假设数据位于第一个工作表

        Iterator<Row> rowIterator = sheet.iterator();

        // 跳过表头
        if (rowIterator.hasNext()) rowIterator.next();
        if (rowIterator.hasNext()) rowIterator.next();
        List<FiberMaterial> materials = new ArrayList<>();

        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();

            // 假设每列的顺序与提供的表格一致
            String materialName = row.getCell(1).getStringCellValue();
            String materialCode = row.getCell(4).getStringCellValue();
            double plyThickness = row.getCell(13).getNumericCellValue();
            double e1 = row.getCell(20).getNumericCellValue();
            double e2 = row.getCell(21).getNumericCellValue();
            double poissonRatio = row.getCell(22).getNumericCellValue();
            double g12 = row.getCell(23).getNumericCellValue();
//            double tensileModulus = row.getCell(2).getNumericCellValue();
//            double compressiveModulus = row.getCell(3).getNumericCellValue();
////            double poissonRatio = row.getCell(4).getNumericCellValue();
//            double shearModulus = row.getCell(5).getNumericCellValue();
//            double density = row.getCell(6).getNumericCellValue();
//            double primaryThermalExpansion = row.getCell(7).getNumericCellValue();
//            double secondaryThermalExpansion = row.getCell(8).getNumericCellValue();
//            double plyThickness = row.getCell(9).getNumericCellValue();

            materials.add(new FiberMaterial(materialName, materialCode, e1, e2,
                    poissonRatio, g12, plyThickness));
        }

        workbook.close();
        return materials;
    }

    /**
     * 导出数据到Excel文件。
     *
     * @param parsedData   解析后的数据
     * @param outputStream 输出流
     * @throws IOException 如果导出过程中发生IO错误
     */
    public void exportExcel(List<Map<String, String>> parsedData, OutputStream outputStream) throws IOException {
        Workbook workbook = new XSSFWorkbook();
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setWrapText(true); // 启用自动换行
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        Sheet sheet = workbook.createSheet("sheet1");

        // 填充数据
        int rowNum = 0;

        for (Map<String, String> cquad4 : parsedData) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(rowNum);
            row.createCell(1).setCellValue(cquad4.get("name"));
            Cell cell1 = row.createCell(2);
            cell1.setCellValue(cquad4.get("description"));
            cell1.setCellStyle(cellStyle); // 设置自动换行样式
            row.createCell(3).setCellValue(cquad4.get("type"));
//            row.createCell(4).setCellValue(cquad4.get(""));
            Cell cell = row.createCell(4);
            cell.setCellValue(cquad4.get("orderResult") + '\n' + cquad4.get("thicknessResult") + '\n' + cquad4.get("propertyResult"));
            cell.setCellStyle(cellStyle); // 设置自动换行样式
        }
        // 自动调整列宽
        for (int i = 0; i < 6; i++) {
            sheet.autoSizeColumn(i);
        }
        sheet.setColumnWidth(2, 25 * 256);
        // 写入 OutputStream
        workbook.write(outputStream);
        workbook.close();
    }
}
